<template>
    <div class="v-text-field">
        <div tabindex="0" class="et-input mb-[2px]! bg-[white] cursor-pointer!" @click="handleClick"
            @dragover.stop="handleDragOver" @dragleave.stop="handleDragLeave" @drop.stop="handleDrop"
            :class="{ 'is-dragging': isDragging }">
            <div class="upload">
                <div class="v-input__control flex! items-center! justify-center! h-[100px]!">
                    <div class="text-center!">
                        <div class="flex! items-center! justify-center!">
                            <img src="/upload/1264360aa13qa26.png" alt="Upload Icon" class="w-12! h-12! inline-block!">
                            <h1 class="text-[#333]! text-[15px]! ml-2">Upload</h1>
                        </div>
                        <p class="text-[#666]! text-[14px]!">drag or click to upload</p>
                    </div>
                </div>
            </div>

            <input type="file" name="file" class="hidden" @change="handleChange" multiple ref="fileInput">
        </div>
        <!-- 文件预览区域 -->
        <div class="preview-container" v-if="selectedFiles.length > 0">
            <div class="preview-item bg-[#fff]!" v-for="(file, index) in selectedFiles" :key="index">
                <div
                    class="text-left font-bold! w-[50%]! inline-block! overflow-hidden! whitespace-nowrap text-ellipsis">
                    <span class="file-name text-[12px]! mr-2">
                        {{ file.name }}
                    </span>
                    <span class="file-size">({{ file.size }}kb)</span>
                </div>
                <div class="flex-1! w-[1px] ml-2">
                    <div class="upload-progress w-full!">
                        <div class="progress-bar"
                            :style="{ width: uploadProgress[index] ? uploadProgress[index] + '%' : '0%' }" :class="{
                                'progress-success': uploadStatus[index] === 'success',
                                'progress-error': uploadStatus[index] === 'error'
                            }">
                        </div>
                    </div>
                </div>
                <button class="remove-btn ml-2!" @click="removeFile(index)">×</button>
            </div>
        </div>
        <div class="h-[22px]! v-input__details">
            <div class="v-messages">
                <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, nextTick, onMounted } from 'vue';
const { $uploadFile } = useNuxtApp()

// 定义组件属性
const props = defineProps({
    multiple: {
        type: Boolean,
        default: true
    },
    accept: {
        type: String,
        default: ''
    },
    maxSize: {
        type: Number,
        default: 10 * 1024 * 1024 // 默认10MB
    },
    maxFiles: {
        type: Number,
        default: 20
    },
    uploadUrl: {
        type: String,
        default: '/index/ajax/upload'
    }
});

const emit = defineEmits(['upload', 'remove', 'error', 'complete']);

const fileInput = ref<HTMLInputElement | null>(null);
const isDragging = ref(false);
const selectedFiles = ref<File[]>([]);
const uploadProgress = ref<Record<number, number>>({});
const uploadStatus = ref<Record<number, 'pending' | 'uploading' | 'success' | 'error'>>({});
const errorMessage = ref('');

// 处理点击上传
const handleClick = (e: Event) => {
    fileInput.value?.click();
};

// 处理文件拖入
const handleDragOver = (e: DragEvent) => {
    e.preventDefault();
    isDragging.value = true;
};

// 处理文件拖离
const handleDragLeave = (e: DragEvent) => {
    e.preventDefault();
    isDragging.value = false;
};

// 处理文件放置
const handleDrop = (e: DragEvent) => {
    e.preventDefault();
    isDragging.value = false;

    if (e.dataTransfer?.files.length) {
        processFiles(Array.from(e.dataTransfer.files));
    }
};

// 处理文件选择
const handleChange = (e: Event) => {
    const target = e.target as HTMLInputElement;
    if (target.files?.length) {
        processFiles(Array.from(target.files));
        // 重置input，允许重复选择同一文件
        target.value = '';
    }
};

// 处理文件并上传
const processFiles = (files: File[]) => {
    errorMessage.value = '';

    // 检查文件数量限制
    if (selectedFiles.value.length + files.length > props.maxFiles) {
        errorMessage.value = `The maximum number of files allowed is ${props.maxFiles}`;
        emit('error', errorMessage.value);
        return;
    }

    // 过滤和验证文件
    const validFiles = files.filter(file => {
        // 检查文件类型
        if (props.accept && !file.type.match(new RegExp(props.accept, 'i'))) {
            errorMessage.value = `The file type is not supported: ${file.name}`;
            emit('error', errorMessage.value);
            return false;
        }

        // 检查文件大小
        if (file.size > props.maxSize) {
            errorMessage.value = `The file size exceeds the limit: ${file.name}`;
            emit('error', errorMessage.value);
            return false;
        }

        return true;
    });

    if (validFiles.length > 0) {
        selectedFiles.value = [...selectedFiles.value, ...validFiles];

        // 触发上传事件并开始上传
        validFiles.forEach((file, index) => {
            const fileIndex = selectedFiles.value.length - validFiles.length + index;
            uploadStatus.value[fileIndex] = 'pending';
            uploadProgress.value[fileIndex] = 0;

            // 延迟执行上传，确保UI有时间更新
            nextTick(() => {
                uploadFile(fileIndex, file);
            });
        });
    }
};

// 上传文件
const uploadFile = async (index: number, file: File) => {
    uploadStatus.value[index] = 'uploading';
    emit('upload', file);

    try {
        const response = await $uploadFile(props.uploadUrl, file, (progress: number) => {
            uploadProgress.value[index] = progress;
        });

        uploadStatus.value[index] = 'success';
        console.log('上传成功:', response);
        emit('complete', { file, response, index });
    } catch (error) {
        uploadStatus.value[index] = 'error';
        console.error('上传失败:', error);
        emit('error', `The file upload failed: ${file.name}`);
    }
};

// 移除文件
const removeFile = (index: number) => {
    const removedFile = selectedFiles.value[index];
    selectedFiles.value.splice(index, 1);
    emit('remove', removedFile);

    // 清理相关状态
    delete uploadProgress.value[index];
    delete uploadStatus.value[index];
};

// 格式化文件大小
const formatFileSize = (bytes: number) => {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

onMounted(() => {
    // 添加全局拖放事件监听器，防止页面重定向
    document.addEventListener('dragover', (e) => {
        e.preventDefault();
    });

    document.addEventListener('drop', (e) => {
        e.preventDefault();
    });
});
</script>

<style lang="scss" scoped>
.preview-container {
    margin-top: 10px;
}

.preview-item {
    display: flex;
    align-items: center;
    padding: 8px;
    border: 1px solid #eee;
    border-radius: 4px;
    margin-bottom: 8px;
}

.preview-info {}

.file-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.file-size {
    font-size: 12px;
    color: #666;
}

.upload-progress {
    height: 6px;
    background-color: #f0f0f0;
    border-radius: 3px;
    margin-top: 4px;
    overflow: hidden;
}

.progress-bar {
    height: 100%;
    background-color: #42b983;
    transition: width 0.3s;
}

.progress-success {
    background-color: #42b983;
}

.progress-error {
    background-color: #ff4d4f;
}

.remove-btn {
    background: none;
    border: none;
    font-size: 16px;
    cursor: pointer;
    color: #999;
    width: 24px;
    height: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background-color 0.2s;

    &:hover {
        background-color: #f5f5f5;
        color: #333;
    }
}

.status-icon {
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 8px;
}

.error-message {
    color: #ff4d4f;
    font-size: 12px;
}

.is-dragging {
    border: 2px dashed #42b983;
}
</style>